//
//  AlbumDetailViewController.swift
//  GhostWorld
//
//  Created by Kam on 2018/4/6.
//  Copyright © 2018 LKGood. All rights reserved.
//

import UIKit
import PKHUD

private let albumDetailInfoCellIdentifier = "AlbumDetailInfoCell"
private let opButtonsCellIdentifier = "AlbumDetailOpCell"
private let audioCellIdentifier = "AudioTableCell"

class AlbumDetailViewController: BaseViewController {
  
  // MARK: - IBOutlets
  
  @IBOutlet weak var tableView: UITableView!
  
  
  // MARK: - Private vars
  
  private var isFirstLoaded = true
  private var audios: [Audio]?
  private var album: Album?
  
  private var favBarButtonItem: UIBarButtonItem?
  private var favAlbum: FavAlbum?
  
  private var audioSortType: AudioSortType = .descending
  
  private var isAlbumPurchaseStateLoaded = false
  private var isUserPurchased = false
  private var userPurchaseDateString: String?
  private var isPurchasedByIAP = false
  
  private var isAlbumOperatable: Bool {
    if album?.isVipContent == true {
      // vip content
      return UserManager.shared.currentUser?.isPremium == true
    } else {
      // non vip content
      if isAlbumPurchaseStateLoaded {
        if album?.isFree == true {
          return true
        } else {
          return isUserPurchased
        }
      } else {
        return false
      }
    }
  }

  
  // MARK: - Private methods
  
  private func getSortedAudios(sortType: AudioSortType) -> [Audio]? {
    if let audios = self.audios {
      return audios.sorted {
        switch self.audioSortType {
        case .ascending:
          return $0.id < $1.id
        case .descending:
          return $0.id > $1.id
        }
      }
    } else {
      return nil
    }
  }
  
  private func loadData() {
    if albumIdentifier > 0 {
      // load album data
      API.shared.requestAPI (
        APIURLStrings.albumDetail(identifier: albumIdentifier),
        method: .get,
        successCallback: { albumJson in
          
          // process album data
          if let albumDictionary = albumJson["album"].dictionaryObject {
            EntityManager.sync (
              type: Album.self,
              rawObject: [albumDictionary],
              operations: [.update, .insert, .insertRelationships, .updateRelationships, .deleteRelationships],
              completion: { error, albums in
                if error == nil {
                  self.album = albums!.first
                  self.audioSortType = AudioSortType(rawValue: Int(self.album!.audioSortType))!
                  
                  if let audiosArray = albumDictionary["audios"] as? [[String: Any]] {
                    EntityManager.sync (
                      type: Audio.self,
                      rawObject: audiosArray,
                      operations: [.update, .insert],
                      completion: { error, audios in
                        
                        if error == nil {
                            self.audios = audios!
                          if let _ = UserManager.shared.currentUser {
                            API.shared.requestAPI(
                              APIURLStrings.albumPurchaseState(identifier: self.albumIdentifier),
                              method: .get,
                              header: API.shared.memeberHeader,
                              successCallback: { json in
                                self.isUserPurchased = json["purchase_status"]["purchased"].boolValue
                                self.userPurchaseDateString = json["purchase_status"]["date"].string
                                self.isAlbumPurchaseStateLoaded = true
                                self.isPurchasedByIAP = false
                                
                                // check iap state
                                if self.isUserPurchased == false {
                                  do {
                                    if let iapPurchasedItem = try IAPPurchasedItem.get(contentType: "album", id: self.albumIdentifier){
                                      self.isUserPurchased = true
                                      self.userPurchaseDateString = iapPurchasedItem.date!.toString(format: .dateTime)
                                      self.isPurchasedByIAP = true
                                    }
                                  } catch { }
                                }
                                
                                self.prepareFavBarButtonItem()
                                self.tableView.reloadData()
                                UIView.animate(withDuration: 0.3) {
                                  self.tableView.alpha = 1
                                }
                            }) { (message, code) in
                              loggingPrint("[\(code)]: \(message)")
                            }
                          } else {
                            if self.album?.isVipContent == true {
                              self.isUserPurchased = false
                            } else if self.album?.isFree == true {
                              self.isUserPurchased = true
                            } else {
                              self.isUserPurchased = false
                            }
                            
                            self.isAlbumPurchaseStateLoaded = true
                            self.prepareFavBarButtonItem()
                            
                            self.tableView.reloadData()
                            UIView.animate(withDuration: 0.3) {
                              self.tableView.alpha = 1
                            }
                          }
                          
                          self.title = (self.canDisplayBasicInfo ? "节目详情" : self.album!.name)
                        }
                    })
                  }
                }
            })
          }
      }) { (message, code) in
        loggingPrint("[\(code)]: \(message)")
      }
    }
  }
    //MARK: - UI
  private func prepareUI() {
    tableView.register(UINib(nibName: audioCellIdentifier, bundle: nil), forCellReuseIdentifier: audioCellIdentifier)
    tableView.contentInset = UIEdgeInsets.init(top: 30, left: 0, bottom: 40, right: 0)
    tableView.scrollIndicatorInsets = tableView.contentInset
  }
  
  private func setDownloadAllButtonState(opCell: AlbumDetailOpCell) {
    if let notDownloadedAudios = (audios?.filter { $0.localURL == nil }),
      notDownloadedAudios.count > 0 {
      opCell.isDownloadAllButtonHidden = false
    } else {
      opCell.isDownloadAllButtonHidden = true
    }
  }
  
  private func prepareFavBarButtonItem() {
    if isAlbumOperatable && UserManager.shared.currentUser != nil {
      do {
        favAlbum = try FavAlbum.get(albumID: albumIdentifier)
        let imageName = (favAlbum == nil ? "FavItem" : "FavItemHL")
        resetFavBarButtonItem(imageName: imageName)
      } catch let error {
        loggingPrint(error)
        navigationItem.rightBarButtonItem = nil
      }
    } else {
      navigationItem.rightBarButtonItem = nil
    }
  }
  
  private func resetFavBarButtonItem(imageName: String) {
    favBarButtonItem = UIBarButtonItem (
      image: UIImage(named: imageName),
      style: .plain,
      target: self,
      action: #selector(addToFav)
    )
    navigationItem.rightBarButtonItem = favBarButtonItem
  }
  
  @objc private func addToFav() {
    if UserManager.shared.currentUser != nil {
      if favAlbum == nil {
        // add to fav
        if albumIdentifier >= 0 {
          if let favAlbum = FavAlbum.add(albumID: albumIdentifier) {
            self.favAlbum = favAlbum
            resetFavBarButtonItem(imageName: "FavItemHL")
            HUD.flash(.labeledSuccess(title: "节目已收藏", subtitle: nil), delay: 1.5)
            return
          }
        }
        HUD.flash(.labeledError(title: "节目收藏失败", subtitle: nil), delay: 1.5)
      } else {
        // remove from fav
        do {
          try FavAlbum.remove(favAlbum!)
          resetFavBarButtonItem(imageName: "FavItem")
          self.favAlbum = nil
          HUD.flash(.labeledSuccess(title: "节目已取消收藏", subtitle: nil), delay: 1.5)
        } catch {
          HUD.flash(.labeledError(title: "取消节目收藏失败", subtitle: nil), delay: 1.5)
        }
      }
    } else {
      displayLoginView(message: "请登录后再收藏节目")
    }
  }
  
  private func displayLoginView(message: String) {
    let alert = UIAlertController (
      title: "尚未登录",
      message: message,
      cancelTitle: "取消",
      cancelHandler: nil,
      confirmTitle: "登录") { _ in
        let loginViewController = UIStoryboard(name: "Account", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
        loginViewController.addCloseButton()
        let nav = BaseNavigationController(rootViewController: loginViewController, dismissDelegate: self)
        nav.isPresentedModally = true
        self.present(nav, animated: true)
    }
    present(alert, animated: true)
  }
  
  private func addNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(downloadFinished(notifiation:)), name: .downloadFinished, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(streamingCacheFinished), name: .streamingCacheFinished, object: nil)
  }
  
  @objc private func downloadFinished(notifiation: Notification) {
    let opCellIndexPath = IndexPath (
      row: (canDisplayBasicInfo ? 1 : 0),
      section: 0
    )
    if let cell = tableView.cellForRow(at: opCellIndexPath) as? AlbumDetailOpCell {
      setDownloadAllButtonState(opCell: cell)
    }
  }
  
  @objc private func streamingCacheFinished() {
    let opCellIndexPath = IndexPath (
      row: (canDisplayBasicInfo ? 1 : 0),
      section: 0
    )
    if let cell = tableView.cellForRow(at: opCellIndexPath) as? AlbumDetailOpCell {
      setDownloadAllButtonState(opCell: cell)
    }
  }
  
  // MARK: - Public vars
  
  var albumIdentifier: Int = -1
  var canDisplayBasicInfo = true
  
  // MARK: - Lifecycle
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    addNotifications()
    prepareUI()
  }
  
  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    if isFirstLoaded {
      tableView.alpha = 0
    }
  }
  
  override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    
    if isFirstLoaded {
      loadData()
      isFirstLoaded = false
    }
  }
  
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ShowAddToPlayListSegue" {
      let nav = segue.destination as! BaseNavigationController
      nav.dismissDelegate = self
      let addToPlayListStep1ViewController = nav.viewControllers.first as! AddToPlayListStep1ViewController
      addToPlayListStep1ViewController.audios = getSortedAudios(sortType: audioSortType)
    }
  }
  
  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }
  
  deinit {
    NotificationCenter.default.removeObserver(self)
  }
  
  // MARK: - IBActions
  

  
  // MARK: - Public methods
  
  
}

// MARK: - UITableViewDataSource

extension AlbumDetailViewController: UITableViewDataSource {
  
  func numberOfSections(in tableView: UITableView) -> Int {
    return 2
  }
  
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    switch section {
    case 0:
      return canDisplayBasicInfo ? 2 : 1
    case 1:
      return audios?.count ?? 0
    default:
      return 0
    }
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    func prepareOpCell() -> AlbumDetailOpCell {
      let cell = tableView.dequeueReusableCell(withIdentifier: opButtonsCellIdentifier, for: indexPath) as! AlbumDetailOpCell
      cell.delegate = self
      setDownloadAllButtonState(opCell: cell)
      return cell
    }
    
    switch indexPath.section {
    case 0:
      if canDisplayBasicInfo {
        if indexPath.row == 0 {
          // album info cell
          let cell = tableView.dequeueReusableCell(withIdentifier: albumDetailInfoCellIdentifier, for: indexPath) as! AlbumDetailInfoCell
          if album != nil {
            cell.prepare (
              album: album!,
              isUserPurchased: isUserPurchased,
              purchaseDateString: userPurchaseDateString,
              isPurchasedByIAP: isPurchasedByIAP
            )
          }
          cell.delegate = self
          return cell
        } else {
          // op cell
          return prepareOpCell()
        }
      } else {
        // op cell
        return prepareOpCell()
      }
      
    default:
      // audio cell
      let cell = tableView.dequeueReusableCell(withIdentifier: audioCellIdentifier, for: indexPath) as! AudioTableCell
      cell.isButtonsEnabled = isAlbumOperatable
      if let audio = getSortedAudios(sortType: audioSortType)?[indexPath.row] {
        cell.prepare(audio: audio)
      }
      return cell
    }
  }
}

// MARK: - UITableViewDelegate

extension AlbumDetailViewController: UITableViewDelegate {
  
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if indexPath.section == 1 {
        if isAlbumOperatable {
          if let audio = getSortedAudios(sortType: audioSortType)?[indexPath.row],
            let album = audio.album {
            NowPlayingManager.shared.update (
              audioList: getSortedAudios(sortType: audioSortType),
              audioListName: album.name ?? "未知节目",
              audioLsitType: .album,
              audioListRefID: "\(album.id)"
            )
            NowPlayingManager.shared.play(album: album, audio: audio)
          }
        } else {
          displayUnusableHUD()
        }
    }
    tableView.deselectRow(at: indexPath, animated: true)
  }
  
  func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return 44
  }
  
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath.section == 0 {
      return UITableView.automaticDimension
    } else {
      return AudioTableCell.defaultHeight
    }
  }
}

// MARK: - BaseNavigationControllerDismissDelegate

extension AlbumDetailViewController: BaseNavigationControllerDismissDelegate {
  func dismiss(navigationController: BaseNavigationController, completion: (() -> Void)?) {
    dismiss(animated: true, completion: completion)
  }
}

// MARK: - AlbumDetailOpCellDelegate

extension AlbumDetailViewController: AlbumDetailOpCellDelegate {
  
  private func displayUnusableHUD() {
    if album?.isVipContent == true {
      HUD.flash(.labeledError(title: "会员专属节目", subtitle: "请成为会员后再试"), delay: 1.5)
    } else {
      HUD.flash(.labeledError(title: "节目尚未兑换", subtitle: "请兑换后再试"), delay: 1.5)
    }
  }

  func addToPlaylist() {
    if isAlbumOperatable {
      if UserManager.shared.currentUser != nil {
        performSegue(withIdentifier: "ShowAddToPlayListSegue", sender: nil)
      } else {
        displayLoginView(message: "请登录后再加入听单")
      }
    } else {
      displayUnusableHUD()
    }
  }
  
  func downloadAllAudios() {
    if isAlbumOperatable {
      if let audios = getSortedAudios(sortType: audioSortType) {
        audios.forEach {
          if $0.localURL == nil && AudioDownloadManager.shared.audioIsInQueue($0) == false {
            AudioDownloadManager.shared.add(audio: $0)
          }
        }
        if let indexPaths = tableView.indexPathsForVisibleRows {
          tableView.reloadRows(at: indexPaths, with: .automatic)
        }
      }
    } else {
      displayUnusableHUD()
    }
  }
  
  func sortAudios() {
    var newType: AudioSortType = .ascending
    switch audioSortType {
    case .ascending:
      newType = .descending
    case .descending:
      newType = .ascending
    }
    do {
      try album?.updateAudioSortType(newType)
      audioSortType = newType
      tableView.reloadSections(IndexSet(integersIn: 1...1) , with: .automatic)
    } catch { }
  }
}

// MARK: - AlbumDetailInfoCellDelegate

extension AlbumDetailViewController: AlbumDetailInfoCellDelegate {
  func buyAlbum() {
    if UserManager.shared.currentUser != nil {
      let body: [String: Any] = [
        "type": 1,
        "ref_id": albumIdentifier
      ]
      HUD.show(.labeledProgress(title: "请稍后", subtitle: nil))
      API.shared.requestAPI (
        APIURLStrings.exchangeContent,
        method: .post,
        body: body,
        header: API.shared.memeberHeader,
        successCallback: { json in
          
          HUD.flash(.labeledSuccess(title: "兑换成功", subtitle: nil), delay: 1.5)
          NotificationCenter.default.post(name: .reloadPurchasedHistory, object: nil)
          
          // update purchase status
          self.isUserPurchased = true
          self.userPurchaseDateString = Date().toString(format: .dateTime)
          self.tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
          if let visibleIndexPaths = self.tableView.indexPathsForVisibleRows {
            self.tableView.reloadRows(at: visibleIndexPaths, with: .automatic)
          }
          self.prepareFavBarButtonItem()
          
          NotificationCenter.default.post(name: .tokenExchangeSuccess, object: nil)
      }, errorCallback: { (message, code) in
        // MARK: - [WARNING]: Using static string for checking state
        if message == "狮羊曼尼不足，请先充值" {
          HUD.hide()
          let alert = UIAlertController (
            title: "兑换失败",
            message: message,
            cancelTitle: "取消",
            cancelHandler: nil,
            confirmTitle: "去充值",
            confirmHandler: { _ in
              self.performSegue(withIdentifier: "ShowTokenViewControllerFromAlbumDetail", sender: nil)
          })
          self.present(alert, animated: true)
        } else {
          HUD.flash(.labeledError(title: "兑换失败", subtitle: message), delay: 1.5)
        }
      })
    } else {
      displayLoginView(message: "请登录后再进行兑换")
    }
  }
}
